﻿using System;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using Firestarter.DB.Schema.BO;
using Habanero.Base;
using Habanero.BO;

namespace Firestarter.DB.Schema.Logic
{
    public class DBMergeBO<T> : MergeBO<T> where T : class, IMergableBo
    {
        public override bool MustMergeProperty(IBOProp prop)
        {
            return base.MustMergeProperty(prop) && prop.PropertyName != "Approved";
        }
    }

    public class DBMergeDBKey : DBMergeBO<DBKey>
    {
        public override Func<DBKey, bool> MatchBusinessObject(DBKey boToFind)
        {
            return foundBO => boToFind != null && foundBO != null && foundBO.KeyName == boToFind.KeyName;
        }
    }

    public class DBMergeDBPrimaryKey : DBMergeBO<DBPrimaryKey>
    {

        public override Func<DBPrimaryKey, bool> MatchBusinessObject(DBPrimaryKey boToFind)
        {
            return foundBO => boToFind != null && foundBO != null && foundBO.TableName == boToFind.TableName;
        }
    }
    public class DBMergeDBColumn : DBMergeBO<DBColumn>
    {
        protected override void MergeProperties(IBusinessObject fromMergableBo, IBusinessObject toMergableBo)
        {
            DBColumn fromDBColumn = (DBColumn) fromMergableBo;
            
            base.MergeProperties(fromMergableBo, toMergableBo);
        }

        public override Func<DBColumn, bool> MatchBusinessObject(DBColumn boToFind)
        {
            return foundBO => boToFind != null && foundBO != null && foundBO.ColumnName == boToFind.ColumnName;
        }
    }

    public class DBMergeDBTable : DBMergeBO<DBTable>
    {
        public override DBTable MergeBOFrom(DBTable fromBO, DBTable toBO)
        {
            //Needed to ensure that all columns have been created when required you merge PK, Key and FK.
            toBO = MergeTablesColumnsOnly(fromBO, toBO);
            this.CopyRelationships(fromBO, toBO);
            return toBO;
        }
        public override bool MustMergeProperty(IBOProp prop)
        {
            return base.MustMergeProperty(prop) && prop.PropertyName != "TableType";
        }
        internal DBTable MergeTablesColumnsOnly(DBTable fromBO, DBTable toBO)
        {
            if (toBO == null)
            {
                toBO = this.CreateBusinessObject();
            }
            this.MergeProperties(fromBO, toBO);

            IMultipleRelationship fromColumnsRelationship = (IMultipleRelationship) fromBO.Relationships["Columns"];
            IMultipleRelationship toColumnsRelationship = (IMultipleRelationship) toBO.Relationships["Columns"];
            if(fromColumnsRelationship != null)
            {
                MergeMultipleRelationship(fromColumnsRelationship, toColumnsRelationship);
            }
            return toBO;
        }

/*        protected override void CopyRelationships(DBTable fromBO, DBTable toBO)
        {
            base.CopyRelationships(fromBO, toBO);
        }*/
    }
    public class DBMergeDBDatabase : DBMergeBO<DBDatabase>
    {
        public override DBDatabase MergeBOFrom(DBDatabase fromBO, DBDatabase toBO)
        {
            if (toBO == null)
            {
                toBO = this.CreateBusinessObject();
            }
            this.MergeProperties(fromBO, toBO);
            var toBOCol = toBO.Tables;
            DBMergeDBTable mergeTable = (DBMergeDBTable) MergeableBORegistry.Instance.Resolve<DBTable>();
            //Needed to ensure that all Table have been created with 
            //  all the required columns have been created when required you merge PK, Key and FK.
            foreach (var fromTable in fromBO.Tables)
            {
                var foundTable = mergeTable.FindBusinessObject(toBOCol, fromTable);
                if (foundTable == null)
                {
                    foundTable = mergeTable.CreateBusinessObject();
                    toBOCol.Add(foundTable);
                }
                foundTable = mergeTable.MergeTablesColumnsOnly(fromTable, foundTable);
                toBOCol.Add(foundTable);
            }

            this.CopyRelationships(fromBO, toBO);
            return toBO;
        }
/*        protected override void CopyRelationships(DBDatabase fromBO, DBDatabase toBO)
        {
            base.CopyRelationships(fromBO, toBO);
        }*/
    }
}